home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Periodicals / develop / develop Issue 6 / develop 6 code / TCP / NewsWatcher / NewsWatcher 2.0d15 source / source / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-11  |  15.7 KB  |  655 lines  |  [TEXT/KAHL]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     util.c
  4.  
  5.     This module contains miscellaneous utility routines.
  6.     
  7.     Portions copyright © 1990, Apple Computer.
  8.     Portions copyright © 1993, Northwestern University.
  9.  
  10. ----------------------------------------------------------------------------*/
  11.  
  12. #include <string.h>
  13.  
  14. #include "glob.h"
  15. #include "util.h"
  16. #include "dlgutil.h"
  17. #include "mouse.h"
  18. #include "activate.h"
  19. #include "draw.h"
  20. #include "menus.h"
  21.  
  22.  
  23.  
  24. static CStr255 gStatusMsg;
  25. static OSErr gMemError = noErr;
  26.  
  27.  
  28.  
  29. /*    IsEqualFSSpec compares two canonical FSSpec records for equality.
  30. */
  31.  
  32. Boolean IsEqualFSSpec (FSSpec *file1, FSSpec *file2)
  33. {
  34.     return
  35.         file1->vRefNum == file2->vRefNum &&
  36.         file1->parID == file2->parID &&
  37.         EqualString(file1->name, file2->name, false, true);
  38. }
  39.  
  40.  
  41.  
  42. /*    GiveTime is called whenever the application is waiting for a slow
  43.     process to complete.  The routine calls SpinCursor and WaitNextEvent
  44.     to give time to currently running background applications.
  45. */
  46.  
  47. Boolean GiveTime (void)
  48. {
  49.     EventRecord ev;
  50.     Boolean gotEvt;
  51.     static long nextTime = 0;
  52.     char keyPressed, charPressed;
  53.     WindowPtr statusWind;
  54.     GrafPtr savePort;
  55.     ControlHandle cancel;
  56.     long myticks;
  57.     short part;
  58.     WindowPtr theWindow;
  59.  
  60.     HiliteMenu(0);
  61.     SetMenusTo(false, 0, 0, 0, 0, 0, 0);
  62.     ShowCursor();
  63.     
  64.     if (TickCount() >= nextTime) {
  65.             
  66.         SpinCursor(16);
  67.  
  68.         gotEvt = WaitNextEvent(everyEvent,&ev,0,nil);
  69.         
  70.         if ( gotEvt )
  71.             switch (ev.what) {
  72.                 case mouseDown:
  73.                     part = FindWindow(ev.where, &theWindow);
  74.                     if (part == inMenuBar) {
  75.                         MenuSelect(ev.where);
  76.                     } else if (IsStatusWindow(FrontWindow())) {
  77.                         HandleMouseDown(&ev);
  78.                     }
  79.                     break;
  80.                 case activateEvt:
  81.                     HandleActivate((WindowPtr)ev.message,
  82.                         ((ev.modifiers & activeFlag) != 0)); 
  83.                     break;
  84.                 case updateEvt:
  85.                     HandleUpdate((WindowPtr)(ev.message));
  86.                     break;
  87.                 case app4Evt:
  88.                     HandleSuspendResume(ev.message);
  89.                     break;
  90.                 case keyDown:
  91.                 case autoKey:
  92.                     FlushEvents(keyDownMask+keyUpMask+autoKeyMask,0);
  93.                     charPressed = ev.message & charCodeMask;
  94.                     keyPressed = (ev.message & keyCodeMask) >> 8;
  95.                     if (keyPressed == escapeKeyCode || 
  96.                         (ev.modifiers & cmdKey) != 0 && charPressed == '.') {
  97.                         statusWind = FrontWindow();
  98.                         if (IsStatusWindow(statusWind)) {
  99.                             cancel = ((WindowPeek)statusWind)->controlList;
  100.                             GetPort(&savePort);
  101.                             SetPort(statusWind);
  102.                             HiliteControl(cancel,1);
  103.                             Delay(8,&myticks);
  104.                             HiliteControl(cancel,0);
  105.                             SetPort(savePort);
  106.                         }
  107.                         gCancel = true;
  108.                     }
  109.                     break;
  110.             }
  111.         nextTime = TickCount() + 5;
  112.     }
  113.  
  114.     return !gCancel;
  115. }
  116.  
  117.  
  118. /*    StatusWindow displays a movable-modal status window indicating
  119.     the current state of the program.
  120. */
  121.  
  122. Boolean StatusWindow (char *text)
  123. {
  124.     WindowPtr statusWind;
  125.     Rect bounds = {0,0,75,420};
  126.     Rect buttonBounds = {42,347,62,407};
  127.     Rect msgBounds = {13, 13, 40, 420};
  128.     TWindow **info;
  129.     
  130.     if (!IsStatusWindow(statusWind = FrontWindow())) {
  131.         if (PtInRect(gPrefs.statusWindowLocn,&gDesktopExtent))
  132.             OffsetRect(&bounds,
  133.                 gPrefs.statusWindowLocn.h,
  134.                 gPrefs.statusWindowLocn.v);
  135.         else
  136.             OffsetRect(&bounds,100,100);
  137.         info = (TWindow**) MyNewHandle(sizeof(TWindow));
  138.         if (MyMemErr() != noErr)
  139.             return false;
  140.         strcpy(gStatusMsg,text);
  141.         (**info).kind = kStatus;
  142.         statusWind = NewWindow(nil, &bounds, "\pStatus", true,
  143.             movableDBoxProc, (WindowPtr)-1,
  144.             false, (unsigned long)info);
  145.         SetPort(statusWind);
  146.         NewControl(statusWind, &buttonBounds, "\pCancel", true, 0, 0, 0, 
  147.             pushButProc, 0);
  148.         ValidRect(&statusWind->portRect);
  149.         SpinCursor(0);
  150.     } else {
  151.         SetPort(statusWind);
  152.         strcpy(gStatusMsg,text);
  153.         EraseRect(&msgBounds);
  154.     }
  155.     TextFont(systemFont);
  156.     TextSize(12);
  157.     MoveTo(13,29);
  158.     DrawText(gStatusMsg,0,strlen(gStatusMsg));
  159.     return true;
  160. }
  161.  
  162.  
  163. /*    UpdateStatus is called in response to update events for the status
  164.     window.  This routine will redraw sections of the window as necessary.
  165. */
  166.  
  167. void UpdateStatus (void)
  168. {
  169.     GrafPtr savePort;
  170.     WindowPtr statusWind;
  171.     
  172.     statusWind = FrontWindow();
  173.     if (!IsStatusWindow(statusWind)) return;
  174.     GetPort(&savePort);
  175.     SetPort(statusWind);
  176.     EraseRect(&statusWind->portRect);
  177.     DrawControls(statusWind);
  178.     TextFont(systemFont);
  179.     TextSize(12);
  180.     MoveTo(13,29);
  181.     DrawText(gStatusMsg,0,strlen(gStatusMsg));
  182.     SetPort(savePort);
  183. }
  184.  
  185.  
  186. /*    CloseStatusWindow is called when the status window should be removed.
  187. */
  188.  
  189. void CloseStatusWindow (void)
  190. {
  191.     WindowPtr statusWind;
  192.     GrafPtr savePort;
  193.     TWindow **info;
  194.     
  195.     if (IsStatusWindow(statusWind = FrontWindow())) {
  196.         SetPt(&gPrefs.statusWindowLocn,0,0);
  197.         GetPort(&savePort);
  198.         SetPort(statusWind);
  199.         LocalToGlobal(&gPrefs.statusWindowLocn);
  200.         info = (TWindow**)GetWRefCon(statusWind);
  201.         SetPort(savePort);
  202.         MyDisposHandle((Handle)info );
  203.         DisposeWindow(statusWind);
  204.     }
  205. }
  206.  
  207. /*    MyIOCheck can be called to display the result of a routine returning
  208.     an OSErr.  If the value in err is zero, the routine simply terminates.
  209. */
  210.  
  211. OSErr MyIOCheck (OSErr err)
  212. {
  213.     if (err != noErr) {
  214.         UnexpectedErrorMessage(err);
  215.     }
  216.     return err;
  217. }
  218.  
  219.  
  220. /*    LowMemory is called when the program runs out of useable memory.
  221.     If this is the first time this has happened, the program de-allocates
  222.     lifeboat memory which was allocated when the program was launched.
  223.     Otherwise, the user had better quit.
  224. */
  225.  
  226. static Boolean LowMemory (void)
  227. {
  228.     Boolean result;
  229.     
  230.     if (MyMemErr() != memFullErr) {
  231.         MyIOCheck(MyMemErr());
  232.         return false;
  233.     }
  234.         
  235.     if (gSinking) {
  236.         result = false;
  237.         gOutOfMemory = true;
  238.         ErrorMessage("You have run out of memory");
  239.     }
  240.     else {
  241.         HUnlock(gLifeBoat);
  242.         DisposHandle(gLifeBoat);
  243.         gSinking = true;
  244.         result = true;
  245.         ErrorMessage("Memory is getting low.  Some operations may fail.");
  246.     }
  247.     return result;
  248. }
  249.  
  250.  
  251. /*    This is a wrapper for the NewPtr routine which automatically checks
  252.     the result of the call and takes appropriate action.
  253. */
  254.  
  255. Ptr MyNewPtr (Size byteCount)
  256. {
  257.     Ptr thePtr;
  258.     
  259.     thePtr = NewPtrClear(byteCount);
  260.     if ((gMemError = MemError()) != noErr) {
  261.         if (LowMemory())
  262.             thePtr = MyNewPtr(byteCount);
  263.         else
  264.             thePtr = nil;
  265.     }
  266.     return thePtr;
  267. }
  268.  
  269.  
  270. /*    This is a wrapper for the NewHandle routine which automatically checks
  271.     the result of the call and takes appropriate action.
  272. */
  273.  
  274. Handle MyNewHandle (Size byteCount)
  275. {
  276.     Handle theHndl;
  277.     
  278.     theHndl = NewHandleClear(byteCount);
  279.     if ((gMemError = MemError()) != noErr) {
  280.         if (LowMemory())
  281.             theHndl = MyNewHandle(byteCount);
  282.         else
  283.             theHndl = nil;
  284.     }
  285.     return theHndl;
  286. }
  287.  
  288. /*    This is a wrapper for the SetHandleSize routine which automatically checks
  289.     the result of the call and takes appropriate action.
  290. */
  291.  
  292. void MySetHandleSize (Handle h, Size newSize)
  293. {
  294.     long oldSize;
  295.  
  296.     oldSize = GetHandleSize(h);
  297.     SetHandleSize(h,newSize);
  298.     if ((gMemError = MemError()) != noErr) {
  299.         if (LowMemory())
  300.             MySetHandleSize(h,newSize);
  301.     } else if (oldSize < newSize) {
  302.         memset(*h+oldSize, 0, newSize-oldSize);
  303.     }
  304. }
  305.  
  306.  
  307. /*    This is a wrapper for the HandToHand routine which automatically checks
  308.     the result of the call and takes appropriate action.
  309. */
  310.  
  311. OSErr MyHandToHand (Handle *theHndl)
  312. {
  313.     Handle oldHndl;
  314.     OSErr result;
  315.     
  316.     oldHndl = *theHndl;
  317.     result = gMemError = HandToHand(theHndl);
  318.     if (result != noErr) {
  319.         *theHndl = oldHndl;
  320.         if (LowMemory())
  321.             result = MyHandToHand(theHndl);
  322.     }
  323.     return result;
  324. }
  325.  
  326.  
  327. /*    This is a wrapper for the DisposPtr routine which automatically checks
  328.     the result of the call and takes appropriate action.
  329.     NT: extra errorchecking for stability incorporated
  330. */
  331.  
  332. OSErr MyDisposPtr (Ptr thePtr)
  333. {
  334.     if(thePtr != nil)
  335.     {
  336.         DisposPtr(thePtr);
  337.         gMemError = MemError();
  338.     }
  339.     else
  340.     {
  341.         gMemError = noErr;
  342.     }
  343.     return MyIOCheck(gMemError);
  344. }
  345.  
  346.  
  347. /*    This is a wrapper for the DisposHandle routine which automatically checks
  348.     the result of the call and takes appropriate action.
  349.     NT: extra errorchecking for stability incorporated
  350. */
  351.  
  352. OSErr MyDisposHandle (Handle theHndl)
  353. {
  354.     if(theHndl != nil)
  355.     {
  356.         DisposHandle(theHndl);
  357.         gMemError = MemError();
  358.     }
  359.     else
  360.     {
  361.         gMemError = noErr;
  362.     }
  363.     return MyIOCheck(gMemError);
  364. }
  365.  
  366.  
  367. /*    This is a wrapper for the MemError routine which automatically checks
  368.     the result of the call and takes appropriate action.
  369. */
  370.  
  371. OSErr MyMemErr (void)
  372. {
  373.     return gMemError;
  374. }
  375.  
  376.  
  377. /*    IsAppWindow returns true if the window belongs to the application
  378. */
  379.  
  380. Boolean IsAppWindow (WindowPtr wind)
  381. {
  382.     short        windowKind;
  383.     
  384.     if (wind == nil)
  385.         return false;
  386.     else {
  387.         windowKind = ((WindowPeek)wind)->windowKind;
  388.         return windowKind >= userKind;
  389.     }
  390. }
  391.  
  392.  
  393. /*    IsDAWindow returns true if the window is a DA window
  394. */
  395.  
  396. Boolean IsDAWindow (WindowPtr wind)
  397. {
  398.     if (wind == nil)
  399.         return false;
  400.     else    /* DA windows have negative windowKinds */
  401.         return ((WindowPeek) wind)->windowKind < 0;
  402. }
  403.  
  404.  
  405. /*    IsStatusWindow returns true if the window is the status window.
  406. */
  407.  
  408. Boolean IsStatusWindow (WindowPtr wind)
  409. {
  410.     TWindow **info;
  411.  
  412.     if (!IsAppWindow(wind)) return false;
  413.     info = (TWindow**)GetWRefCon(wind);
  414.     return (**info).kind==kStatus;
  415. }
  416.  
  417.  
  418. /*    pstrcpy copies Pascal format strings.
  419. */
  420.  
  421. void pstrcpy (StringPtr to, StringPtr from)
  422. {
  423.     BlockMove(from, to, *from+1);
  424. }
  425.  
  426.  
  427. /*    GetPixelDepth gets the pixel depth of the monitor with the 
  428.     maximum intersection with a given rectangle.
  429.     
  430.     Entry:    *r = rectangle in local coord system of current port.
  431.     
  432.     Exit:    function result = pixel depth.
  433. */
  434.  
  435. short GetPixelDepth (Rect *r)
  436. {
  437.     Rect tempRect;
  438.     GDHandle theDev;
  439.     PixMapHandle theMap;
  440.     
  441.     if (!gHasColorQD) return 1;
  442.     tempRect = *r;
  443.     LocalToGlobal((Point*)&tempRect.top);
  444.     LocalToGlobal((Point*)&tempRect.bottom);
  445.     theDev = GetMaxDevice(&tempRect);
  446.     if (theDev == nil) return 1;
  447.     theMap = (**theDev).gdPMap;
  448.     if (theMap == nil) return 1;
  449.     return (**theMap).pixelSize;
  450. }
  451.  
  452. /*    VolNameToVRefNum returns a volume reference number given a volume name. */
  453.  
  454. OSErr VolNameToVRefNum (StringPtr name, short *vRefNum)
  455. {
  456.     HParamBlockRec pb;
  457.     Str31 volNameWithColon;
  458.     short len;
  459.     OSErr err;
  460.     
  461.     pstrcpy(volNameWithColon, name);
  462.     len = *volNameWithColon;
  463.     if (volNameWithColon[len] != ':') {
  464.         len = ++(*volNameWithColon);
  465.         volNameWithColon[len] = ':';
  466.     }
  467.     pb.volumeParam.ioNamePtr = volNameWithColon;
  468.     pb.volumeParam.ioVolIndex = -1;
  469.     err = PBHGetVInfo(&pb, false);
  470.     *vRefNum = pb.volumeParam.ioVRefNum;
  471.     return err;
  472. }
  473.  
  474.  
  475.  
  476. /*    GetFontNumber - Get font number corresponding to font name. 
  477.     Returns false if font does not exist. (From Think Ref) */
  478.  
  479.  
  480. Boolean GetFontNumber (Str255 fontName, short *fontNum)
  481. {
  482.     Str255 systemFontName;
  483.  
  484.     GetFNum(fontName, fontNum);
  485.     if (*fontNum == 0) {
  486.         /* Either we didn't find the font, or we were looking for the system
  487.           * font. */
  488.         GetFontName(0, systemFontName);
  489.         return EqualString(fontName, systemFontName, false, false);
  490.     } else {
  491.         return true;
  492.     }
  493. }
  494.  
  495.  
  496. /*    The InitCursorCtl, SpinCursor, strcasecmp and strncasecmp functions 
  497.     are missing in Think, so we include them here    */
  498.  
  499. Handle gAcur = nil;
  500.  
  501. pascal void InitCursorCtl (Handle id)
  502. {
  503.     short NoFrames, i, CursId;
  504.     CursHandle    TheCursHndl;
  505.  
  506.     if (id == nil) {
  507.         gAcur = (Handle) GetResource('acur',0);
  508.         if(gAcur == nil) return;
  509.         HLock(gAcur);
  510.         NoFrames = ((short *)(*gAcur))[0];
  511.         for(i = 0; i < NoFrames; i++) {
  512.             CursId = ((short *)(*gAcur))[(2*i)+2];
  513.             TheCursHndl = GetCursor(CursId);
  514.             ((CursHandle *)(*gAcur))[i+1] = TheCursHndl;
  515.             HLock((Handle)TheCursHndl);
  516.         }
  517.     } else {
  518.         gAcur = id;
  519.         HLock(gAcur);
  520.         NoFrames = ((short *)(*gAcur))[0];
  521.         for(i = 0; i < NoFrames; i++) {
  522.             CursId = ((short *)(*gAcur))[(2*i)+2];
  523.             TheCursHndl = GetCursor(CursId);
  524.             ((CursHandle *)(*gAcur))[i+1] = TheCursHndl;
  525.             HLock((Handle)TheCursHndl);
  526.         }
  527.     }
  528.     ((short *)(*gAcur))[1] = 0;
  529.     DetachResource(gAcur);
  530. }
  531.  
  532.  
  533. pascal void SpinCursor (short num)
  534. {
  535.     short    NoFrames, CurrentFrame, CurrentCounter;
  536.     Cursor    CurrentCursor;
  537.  
  538.     if (gAcur == nil) InitCursorCtl(nil);
  539.     NoFrames = ((short *)(*gAcur))[0];
  540.     CurrentCounter = ((((short *)(*gAcur))[1] + num) % (NoFrames * 32));
  541.     ((short *)(*gAcur))[1] = CurrentCounter;
  542.     CurrentFrame = CurrentCounter / 32;
  543.     CurrentCursor = **(((CursHandle *)(*gAcur))[CurrentFrame+1]);
  544.     SetCursor(&CurrentCursor);
  545. }
  546.  
  547.  
  548. /*
  549.  * Copyright (c) 1987 Regents of the University of California.
  550.  * All rights reserved.
  551.  *
  552.  * Redistribution and use in source and binary forms are permitted
  553.  * provided that this notice is preserved and that due credit is given
  554.  * to the University of California at Berkeley. The name of the University
  555.  * may not be used to endorse or promote products derived from this
  556.  * software without specific written prior permission. This software
  557.  * is provided ``as is'' without express or implied warranty.
  558.  */
  559.  
  560. #ifndef u_char
  561.     #define u_char  unsigned char
  562. #endif
  563.  
  564. /*
  565.  * This array is designed for mapping upper and lower case letter
  566.  * together for a case independent comparison.  The mappings are
  567.  * based upon ascii character sequences.
  568.  */
  569. static u_char charmap[] = {
  570.     '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  571.     '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  572.     '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  573.     '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  574.     '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  575.     '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  576.     '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  577.     '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  578.     '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  579.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  580.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  581.     '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  582.     '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  583.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  584.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  585.     '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  586.     '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  587.     '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  588.     '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  589.     '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  590.     '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  591.     '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  592.     '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  593.     '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  594.     '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  595.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  596.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  597.     '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
  598.     '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  599.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  600.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  601.     '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  602. };
  603.  
  604.  
  605. short strcasecmp (const char *s1, const char *s2)
  606. {
  607.     u_char            *cm = charmap;
  608.     const u_char    *us1 = (const u_char *)s1;
  609.     const u_char    *us2 = (const u_char *)s2;
  610.  
  611.     while (cm[*us1] == cm[*us2++])
  612.         if (*us1++ == 0)
  613.             return(0);
  614.     return(cm[*us1] - cm[*--us2]);
  615. }
  616.  
  617.  
  618. short strncasecmp (const char *s1, const char *s2, short n)
  619. {
  620.     u_char            *cm = charmap;
  621.     const u_char    *us1 = (const u_char *)s1;
  622.     const u_char    *us2 = (const u_char *)s2;
  623.  
  624.     while (--n >= 0 && cm[*us1] == cm[*us2++])
  625.         if (*us1++ == 0)
  626.             return(0);
  627.     return(n < 0 ? 0 : cm[*us1] - cm[*--us2]);
  628. }
  629.  
  630. /*------------------------------------------------------------------------
  631.  * SetPortTextStyle
  632.  * Set the text font, size, style, etc. of the current port based
  633.  * on a TextStyle record.
  634.  * NOTE: color field is ignored for now.
  635.  */
  636. void SetPortTextStyle(const TextStyle *style)
  637. {
  638.     TextFont(style->tsFont);
  639.     TextFace(style->tsFace);
  640.     TextSize(style->tsSize);
  641. }
  642.  
  643. /*------------------------------------------------------------------------
  644.  * GetPortTextStyle
  645.  * Get the text font, size, style, etc. of the current port.
  646.  * NOTE: color field is ignored for now.
  647.  */
  648. void GetPortTextStyle(TextStyle *style)
  649. {
  650.     style->tsFont = qd.thePort->txFont;
  651.     style->tsFace = qd.thePort->txFont;
  652.     style->tsSize = qd.thePort->txFont;
  653. }
  654.  
  655.